1 module util;
2 
3 const(char)[] removeUnicodeBOM(const(char)[] input) {
4 	if (input.length >= 3 && input[0 .. 3] == "\xef\xbb\xbf") {
5 		return input[3 .. $];
6 	} else {
7 		return input;
8 	}
9 }
10 
11 pure string replace(string text, string oldText, string newText, bool caseSensitive = true, bool first = false) {
12 	import std.uni : toLower;
13 
14 	string ret;
15 	string tempData;
16 	bool stop;
17 	foreach(char c; text) {
18 		if (tempData.length > oldText.length && !stop) {
19 			ret ~= tempData;
20 			tempData = "";
21 		}
22 		if (((caseSensitive && oldText[0 .. tempData.length] != tempData) || (!caseSensitive && oldText[0 .. tempData.length].toLower() != tempData.toLower())) && !stop) {
23 			ret ~= tempData;
24 			tempData = "";
25 		}
26 		tempData ~= c;
27 		if (((caseSensitive && tempData == oldText) || (!caseSensitive && tempData.toLower() == oldText.toLower())) && !stop) {
28 			ret ~= newText;
29 			tempData = "";
30 			stop = first;
31 		}
32 	}
33 	if (tempData != "") {
34 		ret ~= tempData;
35 	}
36 	return ret;
37 }
38 
39 string makeValidCIdentifier(string input) {
40 	import std.string : indexOf;
41 	char[] ret;
42 
43 	if (input.length > 0) {
44 		if ((input[0] >= 'a' && input[0] <= 'z') || (input[0] >= 'A' && input[0] <= 'Z') || input[0] == '_') {
45 			return input;
46 		}
47 
48 		ptrdiff_t i = input.indexOf('_');
49 		if (i == -1) {
50 			ret.length = input.length + 1;
51 			ret[0] = '_';
52 			ret[1 .. $] = input;
53 		} else {
54 			ret.length = input.length;
55 			ret[0 .. input.length-(i+1)] = input[i+1 .. $];
56 			ret[input.length-(i+1)] = '_';
57 			if (i > 0)
58 				ret[$-i .. $] = input[0 .. i];
59 		}
60 	}
61 
62 	return (cast(string)ret).makeValidCIdentifier;
63 }
64 
65 unittest {
66 	assert(makeValidCIdentifier("abc") == "abc");
67 	assert(makeValidCIdentifier("_abc") == "_abc");
68 	assert(makeValidCIdentifier("4_abc") == "abc_4");
69 	assert(makeValidCIdentifier("4g_abc") == "abc_4g");
70 	assert(makeValidCIdentifier("4g") == "_4g");
71 	assert(makeValidCIdentifier("") == "");
72 }
73 
74 string fixTypePointer(string input) {
75 	import std.string : strip, startsWith;
76 	if (input is null)
77 		return null;
78 
79 	input = input.strip;
80 
81 	if (input.length > 6 && input[0 .. 6] == "struct")
82 		input = input[6 .. $];
83 
84 	char[] buffer, buffer2;
85 	buffer.length = input.length;
86 	buffer[] = input[];
87 
88 	size_t i;
89 	while(i < buffer.length) {
90 		char c = buffer[i];
91 		char c2 = '\0';
92 
93 		if (i + 1 < buffer.length)
94 			c2 = buffer[i + 1];
95 
96 		if (c == ' ') {
97 			if (c2 == '*') {
98 				buffer[i] = '*';
99 				buffer[i + 1] = ' ';
100 			}
101 		}
102 
103 		i++;
104 	}
105 
106 	string ret = cast(string)buffer.strip;
107 	if (ret == "const GLvoid*  const*" || ret == "const GLchar* const*" || ret == "const void* const*")
108 		return "const(const(GLvoid*)*)";
109 	else if (ret == "const void*  const*")
110 		return "const(void**)";
111 	else if (ret == "GLuitn" || ret == "Gluint")
112 		return "GLuint";
113 	else if (ret == "Glenum*")
114 		return "GLenum*";
115 	else if (ret == "const Glenum*")
116 		return "const(GLenum)*";
117 	else if (ret == "DEBUGPROC")
118 		return "GLDEBUGPROC";
119 	else if (ret == "const GLubyte*" || ret == "const GLubyte *")
120 		return "const(GLubyte)*";
121 	else if (ret.startsWith("const "))
122 		return "const(" ~ ret[6 .. $] ~ ")";
123 	else
124 		return ret;
125 }